package web.servlet.api;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 通用系统命令执行工具类（支持任何命令：adb、git、ls、ping等）
 */
public class CommandExecutor {

    /**
     * 直接执行完整命令字符串（支持任意系统命令）
     * 示例：
     * - executeCommand("git status")
     * - executeCommand("adb devices -l")
     * - executeCommand("ping www.baidu.com -n 3")（Windows）
     * - executeCommand("ls -l /home")（Linux/macOS）
     */
    public static CommandResult executeCommand(String fullCommand, long timeout) {
        // 解析命令字符串为参数列表（支持空格、引号）
        List<String> parsedArgs = parseCommandString(fullCommand);
        // 直接执行解析后的命令（不做任何前缀移除）
        return execute(parsedArgs, timeout);
    }

    /**
     * 重载：默认超时时间30秒
     */
    public static CommandResult executeCommand(String fullCommand) {
        return executeCommand(fullCommand, 30);
    }

    /**
     * 执行参数列表形式的命令（基础方法）
     */
    public static CommandResult execute(List<String> commandArgs, long timeout) {
        Process process = null;
        try {
            // 启动进程执行命令
            ProcessBuilder pb = new ProcessBuilder(commandArgs);
            pb.redirectErrorStream(false); // 分开捕获输出和错误
            process = pb.start();

            // 读取输出流和错误流（自动适配系统编码）
            String output = readStream(process.getInputStream());
            String error = readStream(process.getErrorStream());

            // 等待命令执行完成（带超时）
            boolean isCompleted = process.waitFor(timeout, TimeUnit.SECONDS);
            if (!isCompleted) {
                process.destroy();
                return new CommandResult(false, output, "命令执行超时（超过" + timeout + "秒）", -1);
            }

            // 返回执行结果
            int exitCode = process.exitValue();
            return new CommandResult(exitCode == 0, output.trim(), error.trim(), exitCode);

        } catch (Exception e) {
            return new CommandResult(false, "", "执行命令失败：" + (e.getMessage() != null ? e.getMessage() : e.toString()), -2);
        } finally {
            if (process != null) {
                process.destroy(); // 确保进程销毁
            }
        }
    }

    /**
     * 解析命令字符串（支持空格、引号包裹的参数）
     * 示例：
     * - "git commit -m 'first commit'" → ["git", "commit", "-m", "first commit"]
     * - "ls '/path/with space'" → ["ls", "/path/with space"]
     */
    private static List<String> parseCommandString(String command) {
        List<String> args = new ArrayList<>();
        StringBuilder currentArg = new StringBuilder();
        boolean inQuotes = false;
        char quoteChar = '\u0000';

        for (char c : command.toCharArray()) {
            if (c == '"' || c == '\'') {
                if (inQuotes && c == quoteChar) {
                    // 结束引号
                    inQuotes = false;
                    quoteChar = '\u0000';
                } else if (!inQuotes) {
                    // 开始引号
                    inQuotes = true;
                    quoteChar = c;
                } else {
                    // 引号内的其他引号视为普通字符
                    currentArg.append(c);
                }
            } else if (Character.isWhitespace(c) && !inQuotes) {
                // 空格分割参数（引号内除外）
                if (currentArg.length() > 0) {
                    args.add(currentArg.toString());
                    currentArg.setLength(0);
                }
            } else {
                // 普通字符
                currentArg.append(c);
            }
        }

        // 添加最后一个参数
        if (currentArg.length() > 0) {
            args.add(currentArg.toString());
        }

        return args;
    }

    /**
     * 读取流内容（自动适配系统编码）
     */
    private static String readStream(InputStream is) throws IOException {
        Charset charset = getSystemCharset();
        BufferedReader br = new BufferedReader(new InputStreamReader(is, charset));
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = br.readLine()) != null) {
            sb.append(line).append("\n");
        }
        br.close();
        return sb.toString();
    }

    /**
     * 获取系统字符集（Windows=GBK，其他=UTF-8）
     */
    private static Charset getSystemCharset() {
        if (System.getProperty("os.name").toLowerCase().contains("windows")) {
            return Charset.forName("GBK");
        } else {
            return Charset.forName("UTF-8");
        }
    }

    /**
     * 命令执行结果实体类
     */
    public static class CommandResult {
        private boolean success;
        private String output;
        private String error;
        private int exitCode;

        public CommandResult(boolean success, String output, String error, int exitCode) {
            this.success = success;
            this.output = output;
            this.error = error;
            this.exitCode = exitCode;
        }

        // Getter
        public boolean isSuccess() {
            return success;
        }

        public String getOutput() {
            return output;
        }

        public String getError() {
            return error;
        }

        public int getExitCode() {
            return exitCode;
        }

        @Override
        public String toString() {
            return "CommandResult{" +
                    "success=" + success +
                    ", output='" + output + '\'' +
                    ", error='" + error + '\'' +
                    ", exitCode=" + exitCode +
                    '}';
        }
    }
}